/**
 * Copyright 2018-2020 shenmk & fengshuonan (https://gitee.com/shenmk)
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lcke.common.except;

import com.lcke.common.rest.Result;
import com.lcke.common.util.HttpContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


/**
 * 全局的的异常拦截器（拦截所有的控制器）（带有@RequestMapping注解的方法上都会拦截）
 *
 * @author shenmk
 * @date 2020年10月12日 下午3:19:56
 */
@ControllerAdvice
@Order(-100)
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 逻辑异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(LogicException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result logic(LogicException e) {
        log.error("业务逻辑异常:" + e.getMessage());
        String message = String.format("业务逻辑异常: %s", e.getMessage());
        return Result.error(e.getCode(), message);
    }

    @ExceptionHandler(OperateException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result operate(OperateException e) {
        log.error("操作异常: " + e.getErrorMessage());
        String message = String.format("操作不符合规范: %s", e.getErrorMessage());
        return Result.error(e.getCode(), message);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result methodArgValid(MethodArgumentNotValidException exception) {
        log.error("操作异常: " + exception.getMessage());
        BindingResult result = exception.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> {
                log.error("field" + error.getField() + ", msg:" + error.getDefaultMessage());
                errorMsg.append(error.getDefaultMessage()).append("!");
            });
        }
        String message = String.format("参数检验异常: %s", errorMsg.toString());
        return Result.error(401, message);
    }


    /**
     * 拦截未知的运行时异常
     *
     * @author fengshuonan
     * @Date 2020/2/6 11:15 上午
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public void notFount(Throwable e) throws Exception {
        log.error("运行时异常:", e);
        // todo 记录系统运行时发生的异常
        String message = String.format("服务器未知运行时异常: %s", e.getMessage());
        //return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
        HttpServletRequest request = HttpContext.getRequest();
        HttpServletResponse response = HttpContext.getResponse();
        request.setAttribute("error", message);
        request.getRequestDispatcher(ExceptionController.ERROR_PATH).forward(request, response);
    }
}
